package org.ky.generator.component;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;
import org.ky.generator.base.DefaultGenerator;
import org.ky.generator.config.DatabaseTableConfig;
import org.ky.generator.config.PackageConfig;
import org.ky.generator.util.AttributeHelper;
import org.ky.generator.util.JdbcHelper;

import com.raddle.jdbc.callback.ConnectionCallback;
import com.raddle.jdbc.meta.table.ColumnInfo;
import com.raddle.jdbc.meta.table.TableInfo;
import com.raddle.jdbc.meta.table.TableMetaHelper;

/**
 * SqlMap接口生成器
 * 
 * @author K.y
 * @since 2018-12-06
 *
 */
public class MapperGenerator extends DefaultGenerator {
	/** 是否生成继承接口的SqlMap接口 */
	protected boolean genWithInterface = true;
	/** 生成一般SqlMap接口类的模版 */
	protected static final String TPL_MAPPER = "template/mapper/mapper.vm";
	/** 生成有父级接口的SqlMap接口类的模版 */
	protected static final String TPL_MAPPER_INTERFACE = "template/mapper/mapperWithInterface.vm";
	/** 默认动作 */
	protected static final String DEFUALT_ACTION = "game/value-added-step";

	public static MapperGenerator sqlMapGenerator = new MapperGenerator();

	private MapperGenerator() {
	}

	public static MapperGenerator getInstance() {
		if (sqlMapGenerator == null)
			sqlMapGenerator = new MapperGenerator();
		return sqlMapGenerator;
	}

	public boolean genWithInterface() {
		return genWithInterface;
	}

	/**
	 * 是否生成带有接口的Mapper
	 * 
	 * @param genWithInterface
	 * @return
	 */
	public MapperGenerator genWithInterface(boolean genWithInterface) {
		this.genWithInterface = genWithInterface;
		return this;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void generator() {
		logger.debug("开始生成SqlMap接口");
		List<TableInfo> tiList = (List<TableInfo>) JdbcHelper.createJdbcTemplate().execute(new ConnectionCallback() {
			public Object doInConnection(Connection con) throws SQLException {
				TableMetaHelper metaHelper = new TableMetaHelper(con);
				return metaHelper.getTableInfo(DatabaseTableConfig.getGenTables(), new String[] { "TABLE" });
			}
		});

		for (TableInfo info : tiList) {
			info.setTableName(info.getTableName());
			try {
				if (genWithInterface()) {
					genCrudWithInterface(info, DEFUALT_ACTION);
				} else {
					genMapper(info, DEFUALT_ACTION);
				}
			} catch (Exception e) {
				logger.error("生成表对象的Mapper接口时发生异常", e);
			}
		}
	}

	/**
	 * 生成不带有父接口的SqlMap接口类
	 * 
	 * @param tableInfo
	 * @param module
	 * @param action
	 * @throws Exception
	 */
	public static void genMapper(TableInfo tableInfo, String action) throws Exception {
		List<Map<String, String>> props = new ArrayList<Map<String, String>>();
		for (ColumnInfo columnInfo : tableInfo.getColumnInfos()) {
			Map<String, String> p = new HashMap<String, String>();
			p.put("label", StringUtils.defaultIfEmpty(columnInfo.getComment(),
					AttributeHelper.getPropertyName(columnInfo.getColumnName())));
			p.put("name", AttributeHelper.getPropertyName(columnInfo.getColumnName()));
			props.add(p);
		}
		//
		Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
				"org.apache.velocity.runtime.log.Log4JLogChute");
		Velocity.setProperty("runtime.log.logsystem.log4j.logger", "root");
		Properties properties = new Properties();
		properties.load(MapperGenerator.class.getResourceAsStream("/velocity.properties"));
		Velocity.init(properties);
		VelocityContext context = new VelocityContext();
		context.put("modelName", AttributeHelper.getJavaPropertyName(tableInfo.getTableName()));
		context.put("className", AttributeHelper.getClassName(tableInfo.getTableName()));
		context.put("properties", props);
		context.put("criteria", PackageConfig.getCriteriaPath());
		context.put("package_model", PackageConfig.getModelPath());
		context.put("package_mapper", PackageConfig.getMapperPath());
		context.put("nameUtils", new AttributeHelper());
		Template templateDao = Velocity.getTemplate(TPL_MAPPER);
		Writer writerDao = new FileWriter(new File(PackageConfig.mkdirsPackagePath(PackageConfig.getOnlyMapper()),
				AttributeHelper.getClassName(tableInfo.getTableName()) + "Mapper.java"));
		templateDao.merge(context, writerDao);
		writerDao.close();
	}

	/**
	 * 生成带有父级接口的SqlMap接口类
	 * 
	 * @param tableInfo
	 * @param module
	 * @param action
	 * @throws Exception
	 */
	public static void genCrudWithInterface(TableInfo tableInfo, String action) throws Exception {
		List<Map<String, String>> props = new ArrayList<Map<String, String>>();
		for (ColumnInfo columnInfo : tableInfo.getColumnInfos()) {
			Map<String, String> p = new HashMap<String, String>();
			p.put("label", StringUtils.defaultIfEmpty(columnInfo.getComment(),
					AttributeHelper.getPropertyName(columnInfo.getColumnName())));
			p.put("name", AttributeHelper.getPropertyName(columnInfo.getColumnName()));
			props.add(p);
		}
		// 构建Velocity
		Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
				"org.apache.velocity.runtime.log.Log4JLogChute");
		Velocity.setProperty("runtime.log.logsystem.log4j.logger", "root");
		Properties properties = new Properties();
		properties.load(MapperGenerator.class.getResourceAsStream("/velocity.properties"));
		Velocity.init(properties);
		VelocityContext context = new VelocityContext();
		context.put("modelName", AttributeHelper.getJavaPropertyName(tableInfo.getTableName()));
		context.put("className", AttributeHelper.getClassName(tableInfo.getTableName()));
		context.put("properties", props);
		context.put("package_model", PackageConfig.getModelPath());
		context.put("package_mapper", PackageConfig.getMapperPath());
		context.put("package_base_mapper", PackageConfig.getIBaseMapperPath());
		context.put("nameUtils", new AttributeHelper());
		// VM模版位置
		Template templateDao = Velocity.getTemplate(TPL_MAPPER_INTERFACE);
		// 文件输出路径
		Writer writerDao = new FileWriter(new File(PackageConfig.mkdirsPackagePath(PackageConfig.getOnlyMapper()),
				AttributeHelper.getClassName(tableInfo.getTableName()) + "Mapper.java"));
		templateDao.merge(context, writerDao);
		writerDao.close();
	}
}
